/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cratos.xxgram.platf.util;




import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
import java.sql.SQLException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.ECPointUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.math.ec.ECCurve;


public class ECC
{
   public static final String TAG = "ECC";
    String curve = "secp128r1";
    static
    {
         Security.insertProviderAt(new BouncyCastleProvider(), 1);
         Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    public boolean verifySig(String accessPointPublicKey, String accessPointPublicKeySigned, String buildingPublicKey)
    {
        try
        {
            PublicKey accessPoint = loadPublicKey(curve, base64Decode(accessPointPublicKey));
            PublicKey building = loadPublicKey(curve, base64Decode(buildingPublicKey));
        
            boolean verified = verify(accessPointPublicKey.getBytes(),
                    building, base64Decode(accessPointPublicKeySigned));
            return verified;
        }
        catch (Exception e)
        {
        }
        return false;
    }


    private boolean verify(byte[] data, PublicKey key, byte[] sig) throws Exception
    {
        Signature signer = Signature.getInstance("SHA256withECDSA");
        signer.initVerify(key);
        signer.update(data);
        return signer.verify(sig);
    }

    private byte[] base64Decode(String s) throws UnsupportedEncodingException
    {
        return java.util.Base64.getDecoder().decode(s);
    }

    public PublicKey loadPublicKey(String curve, byte[] data)
            throws SQLException, IOException, GeneralSecurityException
    {
        KeyFactory factory = KeyFactory.getInstance("ECDSA", "SC");
       
        ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curve);
        ECCurve eccCurve = spec.getCurve();
        EllipticCurve ellipticCurve = EC5Util.convertCurve(eccCurve, spec.getSeed());
        java.security.spec.ECPoint point = ECPointUtil.decodePoint(ellipticCurve, data);
        java.security.spec.ECParameterSpec params = EC5Util.convertSpec(ellipticCurve, spec);
        ECPublicKeySpec keySpec = new ECPublicKeySpec(point, params);
        return factory.generatePublic(keySpec);
    }

    public static PrivateKey loadPrivateKey(String curve, byte[] data)
            throws SQLException, IOException, GeneralSecurityException
    {
        KeyFactory factory = KeyFactory.getInstance("EC", "BC");
        ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec(curve);
        ECCurve eccCurve = spec.getCurve();
        EllipticCurve ellipticCurve = EC5Util.convertCurve(eccCurve, spec.getSeed());
        java.security.spec.ECParameterSpec params = EC5Util.convertSpec(ellipticCurve, spec);
        ECPrivateKeySpec keySpec = new ECPrivateKeySpec(new BigInteger(1, data), params);
        return factory.generatePrivate(keySpec);
    }

    public String encryptData(String token, String public_key)
    {
        try
        {
            PublicKey accessPoint = loadPublicKey(curve, base64Decode(public_key));
            Cipher c = Cipher.getInstance("ECDH");
            c.init(Cipher.ENCRYPT_MODE, accessPoint);
            String messageString = token;
            byte[] message = messageString.getBytes();
            byte[] cipher = c.doFinal(message);
            return java.util.Base64.getEncoder().encodeToString(cipher);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    public String decryptData(String message,String private_key)
    {
        try
        {
            PrivateKey privateKey = loadPrivateKey(curve, base64Decode(private_key));
            Cipher c = Cipher.getInstance("ECIES");
            byte[] token = ((java.util.Base64.getDecoder().decode(message.getBytes())));
            c.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] plaintext = c.doFinal(token);
            
            return new String(plaintext);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }
    
    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException {
        ECC ecc = new ECC();
//       String privateKey = "MGoCAQAwEAYHKoZIzj0CAQYFK4EEAAkEUzBRAgEBBBUA8TU5KpJxHffdZ3/zcAj8U0gLCxmgBwYFK4EEAAmhLAMqAATTMDmjh4wyi/59wFnUA7N9RwTvQIMoTn19Grh2y9H49TOhbkMEhzmg";
//       String message = "BGu3JXNW6H+WDNPNdcxCaN9ilGmJhfwY99HYSqao71FYWzG4pDJyntxht7AFRM4UwkcUGDoRcfKt/uVcqXwhHJtqMOSf6uP/MCCaEIb7sHyfbi6GpDieZDeMrH3XeA==";
//       System.out.println("privateKey===" + privateKey);
//       ECC ecc = new ECC();
//        try {
//           String content =  ecc.decryptData(message, privateKey);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

    }
}